/*
 * Copyright (c) 1998 Anhyp, NV. All Rights Reserved.
 *
 * This software is the confidential and proprietary information of Anhyp.
 *
 */

package chabernac.present;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import java.util.StringTokenizer;

/**
 * 
 * 
 * @version v1.0.0 Dec 6, 2005
 * 
 *          <pre>
 * <u><i>Version History</u></i>
 * 
 * v1.0.0 Dec 6, 2005 - initial release       - Guy Chauliac
 * 
 * </pre>
 * 
 * @author <a href="mailto:guy.chauliac@axa.be"> Guy Chauliac </a>
 */
public class PakjesVerdeler {
	private static Random theRandom = new Random();
	private List<Person> persons = null;
	private ArrayList<Person> randomList = null;

	public PakjesVerdeler() {
		persons = new ArrayList<Person>();
	}

	public Person getPerson(String aName) {
		for (Person thePerson : persons) {
			if (thePerson.getName().equals(aName)) {
				return thePerson;
			}
		}
		return null;
	}

	public void addPerson(Person aPerson) {
		Person thePerson = getPerson(aPerson.getName());

		if (thePerson != null) {
			thePerson.setMail(aPerson.getMail());
		} else {
			persons.add(aPerson);
		}
	}

	public boolean verdeel() throws IOException {
		if (!randomize(10)) {
			System.out.println("Mislukt :-(");
			return false;
		}

		writeList();
		sendMessages();

		System.out.println("Hoera! de pakjes zijn verdeeld!");
		return true;
	}

	private void sendMessages() {
		System.out.println("Versturen mails...");
		for (int i = 0; i < randomList.size(); i++) {
			((Person) randomList.get(i)).buyFor((Person) randomList.get((i + 1) % randomList.size()));
		}
	}

	private boolean resendFor(String aUserName, String eMail) throws ClassNotFoundException, IOException {
		loadRandomList();

		for (int i = 0; i < randomList.size(); i++) {
			Person thePerson = randomList.get(i);
			if (thePerson.getName().equalsIgnoreCase(aUserName)) {
				thePerson.setMail(eMail);
				Person thePersonFor = randomList.get((i + 1) % randomList.size());
				thePerson.buyFor(thePersonFor);
				return true;
			}
		}
		return false;
	}

	public void resendMessages() throws ClassNotFoundException, IOException {
		loadRandomList();
		sendMessages();
	}

	public void loadRandomList() throws ClassNotFoundException, IOException {
		ObjectInputStream theInputStream = null;
		try {
			System.out.println("Inlezen vorige verdeling");
			theInputStream = new ObjectInputStream(new FileInputStream(new File("verdeling.bin")));
			randomList = (ArrayList<Person>) theInputStream.readObject();
		} finally {
			if (theInputStream != null) {
				theInputStream.close();
			}
		}
	}

	private void writeList() throws IOException {
		ObjectOutputStream theStream = null;
		try {
			theStream = new ObjectOutputStream(new FileOutputStream("verdeling.bin"));
			theStream.writeObject(randomList);
			theStream.flush();
		} finally {
			if (theStream != null) {
				theStream.close();
			}
		}

	}

	public boolean randomize(int aMaxTries) {
		for (int i = 0; i < aMaxTries; i++) {
			if (randomize())
				return true;
		}
		return false;
	}

	private void populatePersonsFromRandomList() {
		for (Person thePerson : randomList) {
			addPerson(thePerson);
		}
	}

	public boolean randomize() {
		if (randomList != null && !randomList.isEmpty() && persons.isEmpty()) {
			populatePersonsFromRandomList();
		}
		randomList = new ArrayList<Person>(persons.size());

		Person lastPerson = null;
		while (!persons.isEmpty()) {
			if (lastPerson != null && !canBuyForAPerson(lastPerson))
				return false;
			int pos = (Math.abs(theRandom.nextInt())) % persons.size();
			Person theNewPerson = (Person) persons.get(pos);
			if (lastPerson == null || lastPerson.canBuyFor(theNewPerson)) {
				randomList.add(persons.get(pos));
				persons.remove(pos);
				lastPerson = theNewPerson;
			}
		}

		// check if the last person added can buy for the first person
		if (!((Person) randomList.get(randomList.size() - 1)).canBuyFor((Person) randomList.get(0))) {
			System.out.println("Last person cannot buy for first rerandomizing");
			return false;
		}

		return true;

	}

	private boolean canBuyForAPerson(Person lastPerson) {
		for (Person thePerson : persons) {
			boolean canBuy = true;
			for (String notFor : lastPerson.getNotFor()) {
				if (thePerson.getName().equalsIgnoreCase(notFor)) {
					canBuy = false;
				}
			}
			if (canBuy)
				return true;
		}
		System.out.println("No remaing person found for " + lastPerson.getName());
		return false;
	}

	public void readFromFile(File aFile) {
		persons.clear();
		BufferedReader theReader = null;
		try {
			theReader = new BufferedReader(new InputStreamReader(new FileInputStream(aFile)));
			String theLine = null;
			while ((theLine = theReader.readLine()) != null) {
				StringTokenizer theTokenizer = new StringTokenizer(theLine);
				Person thePerson = new Person(theTokenizer.nextToken(), theTokenizer.nextToken());
				while (theTokenizer.hasMoreTokens())
					thePerson.addNotFor(theTokenizer.nextToken());
				addPerson(thePerson);
			}
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	public static void main(String args[]) throws IOException, ClassNotFoundException {

		PakjesVerdeler theContainer = new PakjesVerdeler();
		if (args[0].equals("verdeel")) {
			System.out.println("Starting pakskes verdeler");
			theContainer.readFromFile(new File(args[1]));
			theContainer.verdeel();
		} else if (args[0].equals("resend")) {
			theContainer.resendMessages();
		} else if (args[0].equals("resendfor")) {
			theContainer.resendFor(args[1], args[2]);
		}

	}
}
